/**
*
* @brief	温湿度传感器数据测量
* @author	yun
* @date		2016-12-27
* @desc		温湿度传感器AM2303
* @version	v0.1
*
*/


#include	"platform_temp.h"

#include	"platform_logger.h"

#include	"stm32f2xx.h"
#include	"mxchipWNet.h"

#define 	TEMP_DATA_CLK_INIT			RCC_AHB1PeriphClockCmd
#define 	TEMP_DATA_BTN_PIN         	GPIO_Pin_3
#define 	TEMP_DATA_BTN_Source		GPIO_PinSource3
#define 	TEMP_DATA_BTN_PORT   		GPIOA
#define 	TEMP_DATA_BTN_CLK    		RCC_AHB1Periph_GPIOA
#define		TEMP_DATA_EXTI_Line			EXTI_Line3
#define		TEMP_DATA_EXTI_Handler		EXTI3_IRQHandler
#define		TEMP_DATA_EXTI_IRQn			EXTI3_IRQn

#define		TEMP_TIM					TIM2
#define		TEMP_TIM_IRQn				TIM2_IRQn
#define		TEMP_TIM_Handler			TIM2_IRQHandler
#define		TEMP_TIM_CLK_PORT			RCC_APB1Periph_TIM2
#define		TEMP_TIM_CLK_INIT       	RCC_APB1PeriphClockCmd

#define		TEMP_TIM_Prescaler			(60 - 1)

//设置温度传感器DATA引脚为输入模式,并开启中断
static int temp_data_input(void){
	GPIO_InitTypeDef GPIO_InitStructure;
	TEMP_DATA_CLK_INIT(TEMP_DATA_BTN_CLK, ENABLE);
	
	GPIO_InitStructure.GPIO_Pin = TEMP_DATA_BTN_PIN;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
	GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
	GPIO_Init(TEMP_DATA_BTN_PORT, &GPIO_InitStructure);
	
	GPIO_PinAFConfig(TEMP_DATA_BTN_PORT, TEMP_DATA_BTN_Source, GPIO_AF_TRACE);
	EXTI_InitTypeDef EXTI_InitStructure;
	EXTI_InitStructure.EXTI_Line = TEMP_DATA_EXTI_Line;
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
	//EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_Init(&EXTI_InitStructure);

	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = TEMP_DATA_EXTI_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0X2D;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	return 0;
}

// 设置温度传感器DATA引脚为输入模式，关闭中断
static int temp_data_output(void){
	GPIO_InitTypeDef GPIO_InitStructure;
	TEMP_DATA_CLK_INIT(TEMP_DATA_BTN_CLK, ENABLE);
	
	GPIO_InitStructure.GPIO_Pin = TEMP_DATA_BTN_PIN;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
	GPIO_Init(TEMP_DATA_BTN_PORT, &GPIO_InitStructure);
	
	EXTI_InitTypeDef EXTI_InitStructure;
	EXTI_InitStructure.EXTI_Line = TEMP_DATA_EXTI_Line;
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
	EXTI_InitStructure.EXTI_LineCmd = DISABLE;
	EXTI_Init(&EXTI_InitStructure);
	return 0;
}

// 开启时间测量定时器
static int temp_tim_enable(void){
	TEMP_TIM_CLK_INIT(TEMP_TIM_CLK_PORT, ENABLE);
	TIM_TimeBaseInitTypeDef  TimeBaseStructure;
	TimeBaseStructure.TIM_Period = 999;
	TimeBaseStructure.TIM_Prescaler = TEMP_TIM_Prescaler;
	TimeBaseStructure.TIM_ClockDivision = 0;
	TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInit(TEMP_TIM, &TimeBaseStructure);	
	//120000000
	TIM_UpdateRequestConfig(TEMP_TIM, TIM_UpdateSource_Regular);
	
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; 
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0X2D;  
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 
	NVIC_Init(&NVIC_InitStructure);
	TIM_ITConfig(TEMP_TIM, TIM_IT_Update, ENABLE);
	TIM_Cmd(TEMP_TIM, ENABLE);
	TIM_SetCounter(TEMP_TIM, 0);
	return 0;
}

// 关闭时间测量定时器
static int temp_tim_disable(void){
	TIM_ITConfig(TEMP_TIM, TIM_IT_Update, DISABLE);
	TIM_Cmd(TEMP_TIM, DISABLE);
	return 0;
}

//
static int temp_tim_clear(void){
	TIM_SetCounter(TEMP_TIM, 0);
	return 0;
}

//
// 微妙级别演示
// 延时数不得大于1ms
//
static int temp_tim_delay_us(short int us){
	if(us > 1000){
		return -1;
	}
	
	TEMP_TIM->CNT = 0;
	int temp = 0;
	while(1){
		temp = TIM2->CNT;
		if (temp > us){
			return 0;
		}
	}
}

static unsigned char temp_data_buffer[8] = { 0 };

volatile unsigned char temp_input_bits = 0;
volatile int interval = 0;


platform_temp_callback 	temp_cal_calllback = NULL;

void TEMP_DATA_EXTI_Handler(void){
	int interval, offset, index, bit;
	interval = TEMP_TIM->CNT;
	if(EXTI_GetITStatus(TEMP_DATA_EXTI_Line) != RESET){
		if(GPIO_ReadInputDataBit(TEMP_DATA_BTN_PORT,TEMP_DATA_BTN_PIN) == 0){				
			if(temp_input_bits > 2){
				offset = temp_input_bits - 2;
				index =  offset / 8;
				bit =  7 - offset % 8;
				if(interval > 60){
					temp_data_buffer[index] |= (0x01 << bit);
				} else {
					temp_data_buffer[index] &= ~(0x01 << bit); 
				}
			}
			temp_input_bits  ++;
		}
		TEMP_TIM->CNT = 0;	
		
		EXTI_ClearFlag(TEMP_DATA_EXTI_Line);
		EXTI_ClearITPendingBit(TEMP_DATA_EXTI_Line);
	}
}


// 开始温湿度测量
int platform_temp_start_measure(platform_temp_callback callback){
	temp_cal_calllback = callback;
	temp_data_output();
	temp_tim_enable();
	GPIO_ResetBits(TEMP_DATA_BTN_PORT, TEMP_DATA_BTN_PIN);
	msleep(30);
	GPIO_SetBits(TEMP_DATA_BTN_PORT, TEMP_DATA_BTN_PIN);
	temp_tim_delay_us(15);
	temp_data_input();
	temp_tim_clear();
	temp_input_bits = 0;
	
	for(int i=0; i<5; i++){
				temp_data_buffer[i] = 0;
	}
	
	return 0;
}

// 关闭温湿度测量
int platform_temp_stop_measure(void){
	temp_cal_calllback = NULL;
	temp_tim_disable();
	temp_data_output();
	GPIO_SetBits(TEMP_DATA_BTN_PORT, TEMP_DATA_BTN_PIN);
	return 0;
}

// 测试代码段

//
void TEMP_TIM_Handler(void){
	if(TIM_GetITStatus(TEMP_TIM, TIM_IT_Update) == SET){
		TIM_ClearITPendingBit(TEMP_TIM, TIM_FLAG_Update);

		temp_tim_disable();
		if(temp_input_bits == 42){
			// 校验测量数据
			unsigned char check = 0;
			for(int i=0; i<4; i++){
				check += temp_data_buffer[i];
			}
			
			if(temp_data_buffer[4] == check){
				// 计算温湿度值
				float  humidity= ((int)temp_data_buffer[0] * 256 + temp_data_buffer[1])/10;
				float  temperature= ((float)temp_data_buffer[2] * 256 + temp_data_buffer[3]) / 10;
				if(temp_cal_calllback != NULL){
					temp_cal_calllback(humidity, temperature, 0); 
				}
				return;
			}
		} 
		
		if(temp_cal_calllback != NULL){
			temp_cal_calllback(0, 0, temp_input_bits+1); 
		}
	}
	return;
}


volatile static float s_temp, s_hum;
volatile static int s_bits;

volatile static int s_complete = 0;


static int temp_measure_complete_callback(float h, float t, int err){
	s_complete = 1;
	if(err == -1){
		return 0;
	}
	
	s_temp = t;
	s_hum = h;
	s_bits = err;
	return 0;
}


int platform_temp_test(void){
	log_info_printf("let's go");
	
	while(1){
		platform_temp_start_measure(temp_measure_complete_callback);

		while(s_complete == 0);
		if(s_complete == 1){
				s_complete = 0;
				log_info_printf("temperature= %0.1f  humidity= %0.1f %%   n=%d", s_temp, s_hum, s_bits);
		}
		
		platform_temp_stop_measure();
		msleep(3000);
	}	
}






